package ch7;

/**
 * 嵌套监视器锁死Demo
 * 解决方法：把doProcess中的take操作移到doProcess方法之外
 */

import util.Tools;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class NestedMonitorLockoutDemo {
    private final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
    private int processed = 0;
    private int accepted = 0;

    public static void main(String[] args) throws InterruptedException {
        NestedMonitorLockoutDemo u = new NestedMonitorLockoutDemo();
        u.start();
        int i = 0;
        while (i-- < 100000) {
            u.accept("message" + i);
            Tools.randomPause(100);
        }
    }

    public synchronized void accept(String message) throws InterruptedException {
        // 注意：不要在临界区内调用BlockingQueue的阻塞方法，put方法内部有判断Condition进行等待的语句（队列非满才存数据）
        queue.put(message);
        accepted++;
    }

    protected synchronized void doProcess() throws InterruptedException {
        //注意：不要在临界区内调用BlockingQueue的阻塞方法，take方法内部有判断Condition进行等待的语句（队列非空才取数据）
        String msg = queue.take();
        System.out.println("Process:" + msg);
        processed++;
    }


    public void start() {
        Thread thread = new WorkerThread();
        thread.setName("WorkerThread");
        thread.start();
    }

    public synchronized int[] getStat() {
        return new int[] {accepted, processed};
    }

    class WorkerThread extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    doProcess();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
